
module ServiceFacade {
    
    export module Utilities {
        export class Arr {
            public static Equals(first: Array<any>, second: Array<any>): boolean {
                // if the other array is a falsy value, return
                if (!second)
                    return false;

                // compare lengths - can save a lot of time 
                if (first.length != second.length)
                    return false;

                for (var i = 0, l = first.length; i < l; i++) {
                    // Check if we have nested arrays
                    if (first[i] instanceof Array && second[i] instanceof Array) {
                        // recurse into the nested arrays
                        if (!this.Equals(first[i], second[i]))
                            return false;
                    }
                    else if (first[i] != second[i]) {
                        // Warning - two different object instances will never be equal: {x:20} != {x:20}
                        return false;
                    }
                }
                return true;
            }
        }
    }
    
    export module Core {
        class AjaxCall {
            private xhr: XMLHttpRequest;
            constructor() {
                var xhr: any;
                if (typeof XMLHttpRequest !== 'undefined') {
                    xhr = new XMLHttpRequest();
                }
                else {
                    var versions = [
                        "MSXML2.XmlHttp.5.0",
                        "MSXML2.XmlHttp.4.0",
                        "MSXML2.XmlHttp.3.0",
                        "MSXML2.XmlHttp.2.0",
                        "Microsoft.XmlHttp"
                    ];
                    for (var i = 0; i < versions.length; i++) {
                        try {
                            xhr = new ActiveXObject(versions[i]);
                            break;
                        }
                        catch (e) {
                            // swallow the exception
                        }
                    }
                }
                this.xhr = xhr;
            }

            private send(url: string, callback: (success: boolean, responseData: string) => any, method: string, data: string) {
                this.xhr.open(method, url, false);
                this.xhr.onreadystatechange = () => {
                    if (this.xhr.readyState == XMLHttpRequest.DONE) {
                        var success = false;
                        if (this.xhr.status == 200) {
                            success = true;
                        }
                        callback(success, this.xhr.responseText);
                    }
                };
                if (method == 'POST') {
                    this.xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
                }
                this.xhr.send(data);
            }

            public post(url: string, data: any, callback: (success: boolean, responseData: string) => any) {
                var query: string = JSON.stringify(data);
                this.send(url, callback, 'POST', query);
            }

            public dispose() {
                this.xhr = null;
            }
        }
    
        export class Service {
            static Call(endPoint: string, postData: any, responseHandler: (returnObject: any) => void, ctor?: any): void {
                var call = new AjaxCall();
                call.post(endPoint, postData, (success: boolean, responseData: string) => {
                    call.dispose();
                    if (success) {
                        var response = JSON.parse(responseData);
                        var returnObject = response.d;
                        if (ctor != null) {
                            returnObject = new ctor(returnObject);
                        }
                        responseHandler(returnObject);
                    }
                    else {
                        throw Error("Service call failed with error: " + responseData);
                    }
                });
            }
        }
    }

    
export class FractionService {

    static ConvertFractionToDecimal(fraction: Muel.TypeScriptFacade.TestPlatform.Services.Fraction, callback: (returnVal: number) => void) {
        ServiceFacade.Core.Service.Call(
            "Services/FractionService.asmx/ConvertFractionToDecimal",
            {
                'fraction' : fraction
            },
            callback,
            null
        );
    }


    static ConvertDecimalToFraction(number: number, callback: (returnVal: Muel.TypeScriptFacade.TestPlatform.Services.Fraction) => void) {
        ServiceFacade.Core.Service.Call(
            "Services/FractionService.asmx/ConvertDecimalToFraction",
            {
                'number' : number
            },
            callback,
            Muel.TypeScriptFacade.TestPlatform.Services.Fraction
        );
    }

};
}
module Muel {

export module TypeScriptFacade {

export module TestPlatform {

export module Services {

    export class Fraction {
        public __type: string = "Muel.TypeScriptFacade.TestPlatform.Services.Fraction";
        public Numerator: number;
        private _Numerator: number;
        public Denominator: number;
        private _Denominator: number;
        constructor(data?: any) {
            if (data == null) { return; }
            this.Numerator = data.Numerator; 
            this.Denominator = data.Denominator; 
        }

        public snapshot(): void {
            this._Numerator = this.Numerator; 
            this._Denominator = this.Denominator; 
        }

        public hasChanges(): boolean {
            if (this._Numerator != this.Numerator) { return true; } 
            if (this._Denominator != this.Denominator) { return true; } 
            return false;
        }
    }

}
}
}
}